package com.andnnl.redis;

import com.andnnl.config.ConfigFileHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;

public class RedisSessionOld {
    private static final Logger logger = LoggerFactory.getLogger(RedisSessionOld.class);

    //redis server config
    //private static final String serverIp="192.168.10.58";
    private static final String serverIp;
    private static final int port;
    private static final int maxActive = 1000;
    private static final int maxIdle = 10;
    private static final int maxWait = 5000;
    private static final boolean testOnBorrow = true;
    private static final boolean testOnReturn = true;
    private static JedisPool pool = null;

    static {
        ConfigFileHelper c = new ConfigFileHelper("config");
        serverIp = c.getString("redis.ip");
        logger.info(serverIp);
        port = c.getInt("redis.port", 6379);
    }

    private Jedis session = null;

    private RedisSessionOld(Jedis session) {
        this.session = session;
    }

    /***
     * 获取JedisPool对象.
     * zzz
     *
     * @return
     */
    public synchronized static RedisSessionOld getRedisClient() {
        if (null == pool) {
            JedisPoolConfig config = new JedisPoolConfig();
            //低版本
//			config.setMaxActive(maxActive);
//			config.setMaxIdle(maxIdle);
//			config.setMaxWait(maxWait);
            //高版本
            config.setMaxTotal(maxActive);
            config.setMaxIdle(maxIdle);
            config.setMaxWaitMillis(maxWait);


            config.setTestOnBorrow(testOnBorrow);
            config.setTestOnReturn(testOnReturn);
            pool = new JedisPool(config, serverIp, port);
        }
        return new RedisSessionOld(pool.getResource());
    }

    public synchronized static RedisSessionOld getRedisClient(int prot) {
        if (null == pool) {
            JedisPoolConfig config = new JedisPoolConfig();
            //低版本
//			config.setMaxActive(maxActive);
//			config.setMaxIdle(maxIdle);
//			config.setMaxWait(maxWait);
            //高版本
            config.setMaxTotal(maxActive);
            config.setMaxIdle(maxIdle);
            config.setMaxWaitMillis(maxWait);


            config.setTestOnBorrow(testOnBorrow);
            config.setTestOnReturn(testOnReturn);
            pool = new JedisPool(config, serverIp, port);
        }
        return new RedisSessionOld(pool.getResource());
    }

    public static void main(String[] args) throws InterruptedException {
        RedisSessionOld r = RedisSessionOld.getRedisClient();
        //System.out.println(r.get("sms25"));
        //r.test();

        String key = "sms29";
        r.set(key, "test1 !");
        logger.info(r.get(key));
        r.destroy();


    }

    /***
     * 根据key 获取String值
     *
     * @param key
     * @return
     */
    public String get(String key) {
        String result = null;
        if (null != key) {
            result = session.get(key);

        }
        return result;
    }

    /***
     * 给key设置对象值
     *
     * @param key
     * @param value 只能是String和Map类型
     */
    public String set(String key, Object value) {
        return set(key, value, null);
    }

    /***
     * 给key 设置对象值，并给予过期时间
     *
     * @param key
     * @param value
     * @param seconds
     */
    public String set(String key, Object value, Integer seconds) {
        if (null != key) {
            if (null != value) {
                if (value instanceof String) {
                    String o = (String) value;
                    if (null == seconds) {
                        return session.set(key, o);
                    } else {
                        return session.setex(key, seconds, o);
                    }
                } else if (value instanceof Map) {
                    Map<String, String> valueMap = (Map<String, String>) value;
                    return session.hmset(key, valueMap);
                } else {
//                    new RuntimeException("redis set value must be a String or Map");
                    String o = value.toString();
                    if (null == seconds) {
                        return session.set(key, o);
                    } else {
                        return session.setex(key, seconds, o);
                    }
                }
            }

        }
        return "";
    }

    /***
     * 判断key是否存在
     * @param key
     * @return
     */
    public boolean existsKey(String key) {
        if (null != key && session.exists(key))
            return true;
        return false;
    }

    /***
     *删除key
     *
     * @param key
     * @return
     */
    public Long del(String key) {
        if (null != key && session.exists(key)) {
            return session.del(key);
        }
        return (long) -1;
    }

    public Jedis getSession() {
        return session;
    }

    /***
     * 释放redis对象
     */
    public void destroy() {
//        pool.returnBrokenResource(this.session);
        this.session.close();
    }

    public void lpush(String key, String val) {

        session.lpush(key, val);
    }

    public void expire(String key, int seconds) {

        session.expire(key, seconds);
    }

    public List lrange(String key, int start, int stop) {

        return session.lrange(key, start, stop);
    }

    public Long hset(String key, String field, String value) {
        return this.session.hset(key, field, value);
    }

    public String hget(String key, String field) {
        return this.session.hget(key, field);
    }

    public Map<String, String> hgetAll(final String key) {
        return this.session.hgetAll(key);
    }

    public long incr(String key) {
        return this.session.incr(key);
    }

    public long incrBy(String key, long field) {
        return this.session.incrBy(key, field);
    }

    public long decr(String key) {
        return this.session.decr(key);
    }

    public long decrBy(String key, long field) {
        return this.session.decrBy(key, field);
    }

    /**
     * 以秒为单位，返回给定 key 的剩余生存时间，
     *
     * @param key
     * @return 当 key 不存在时，返回 -2 。 当 key 存在但没有设置剩余生存时间时，返回 -1 。
     * 否则，以秒为单位，返回 key 的剩余生存时间。
     */
    public long ttl(String key) {
        return this.session.ttl(key);
    }

//    /**
//     * RedisSession类的任意方法调用用try包装
//     * @param c 任意方法调用
//     * @return 返回true，false，表示操作是否成功
//     */
//    public static boolean operateTF(Consumer<RedisSession> c) {
//        RedisSession redis = null;
//        try {
//            redis = getRedisClient();
//            if (redis == null) {
//                return false;
//            }
//            c.accept(redis);
//            return true;
//        } catch (Exception e) {
//            logger.error(e.getMessage(), e);
//        } finally {
//            if (redis != null)
//                redis.destroy();
//        }
//        return false;
//    }

    /**
     * RedisSession类的任意方法调用用try包装，并返回值
     * 用法 ：String rsStr=RedisSession.operate(s->s.set("asdf","asdf"));
     * @param c 任意方法调用
     * @return 任意方法的返回值，返回Null，表示操作失败
     */
    public static <R> R operate(Function<RedisSessionOld,R> c) {
        RedisSessionOld redis = null;
        try {
            redis = getRedisClient();
            if (redis == null) {
                return null;
            }
            return c.apply(redis);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (redis != null)
                redis.destroy();
        }
        return null;
    }
    /**
     * 批量操作，RedisSession类的任意方法调用用try包装，并返回值
     * 如果部分成功也会返回List
     * @param list 列表
     * @param c 任意方法调用
     * @return 任意方法的返回值，返回Null，表示操作失败
     */
    public static <U,R> List<R> operate(List<U> list, BiFunction<RedisSessionOld,U, R> c) {
        RedisSessionOld redis = null;
        List<R> result = new ArrayList<>();
        try {
            redis = getRedisClient();
            if (redis == null) {
                return null;
            }
            for (U u : list) {
                result.add(c.apply(redis,u));
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (redis != null)
                redis.destroy();
        }
        return result;
    }

    public void set(byte[] key,byte[] value){
        this.session.set(key,value);
    }

    public void setex(byte[] key,byte[] value,int sec){
        this.session.setex(key,sec,value);
    }

    /**
     *
     * @param key 固定key
     * @param h 权重 号码
     * @param value 值
     */
    public void zadd(byte[] key,double h,byte[] value){
        this.session.zadd(key,h,value);
    }

    /**
     *  @param key 固定key
     * @param from 权重 号码
     * @param to 权重 号码
     * @return
     */
    public Set<byte[]> zrangeByScore(byte[] key, double from, double to){
        return this.session.zrangeByScore(key,from,to);
    }
    public void test() {

        //返回Null,表示操作失败
        String rsStr= RedisSessionOld.operate(s->s.set("asdf","asdf"));
        System.out.println(rsStr);

        Long rs= RedisSessionOld.operate(s->s.del("asdf"));
        System.out.println(rs);

        List<String> list= Arrays.asList("asdf1","asdf2","asdf3");
        List<String> rsStrList= RedisSessionOld.operate(list,(s, b)->s.set(b,b));
        System.out.println(rsStrList);

        List<String> list2= Arrays.asList("asdf1","asdf2","asdf3");
        List<Long> rsStrList2= RedisSessionOld.operate(list,(s, b)->s.del(b));
        System.out.println(rsStrList2);

        //session.del("list");
        session.lpush("27767529587889671719922901515223", "abc");
        session.expire("27767529587889671719922901515223", 15);
        session.lpush("27767529587889671719922901515223", "xzc");
        session.expire("27767529587889671719922901515223", 15);
        session.lpush("27767529587889671719922901515223", "erf");
        session.expire("27767529587889671719922901515223", 15);
        session.lpush("27767529587889671719922901515223", "bnh");
        session.expire("27767529587889671719922901515223", 15);
        //LRANGE key start stop返回列表key中指定区间内的元素，区间以偏移量start和stop指定。下标(index)参数start和stop都以0为底，也就是说，以0表示列表的第一个元素，以1表示列表的第二个元素，以此类推。你也可以使用负数下标，以-1表示列表的最后一个元素，-2表示列表的倒数第二个元素，以此类推。
        List listx = session.lrange("27767529587889671719922901515223", 0, -1);
//	        for(int i=0;i<list.size();i++){
//	            logger.info(list.get(i));
//	        }
    }

}
